package com.jnuo.mdb

import android.text.TextUtils
import java.io.Serializable

/**
 * Created by zhangyuncai on 2021/6/2.
 */
class MdbBean : Serializable {

    var version: String? = null//当前mdb版本,none_version
    var hasEmptyCoinChannel = false//硬币器管道是否有空管道
    var topOrderBalance = 0.0//上次订单封单后余额

    var billVersion: String? = null//纸币器版本
    var billConnectionStatus = false//纸币器链接状态
    var cashlessConnectionStatus = false//刷卡机链接状态

    var coinVersion: String? = null//硬币器版本
    var coinConnectionStatus = false//硬币器链接状态
    var coinTubeLowList: List<MDBRejectAmount>? = null//硬币器中每个币种当前数量和每个币种的低水位信息
    var coinTubeEnableList: List<MDBRejectAmount>? = null//硬币器管道使能信息，显示哪些币值是否有管道
    val coinEnableList: List<MDBRejectAmount>?
        //硬币器中每个币种打开/关闭信息
        get() {
            val list = arrayListOf<MDBRejectAmount>()
            try {
                val mdbExcludeFromNextAmountCoin = MdbParamsHelper.mdb_exclude_from_next_amount_coin
                coinTubeEnableList?.forEach {
                    if (it.enable == 1) {//表示存在这个管道
                        val amount = MDBRejectAmount()

                        val credit = it.credit?.toDouble() ?: 0.0
                        if (!mdbExcludeFromNextAmountCoin.isNullOrEmpty() && mdbExcludeFromNextAmountCoin.contains(credit)) {
                            //在配置文件中获取禁用值
                            amount.enable = 0
                        } else {//默认启用
                            amount.enable = 1
                        }
                        amount.credit = it.credit
                        amount.kind = it.kind
                        amount.num = it.num

                        list.add(amount)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return list
        }

    //纸币器中支持的币种
    var billEnableList: List<MDBRejectAmount>? = null
        get() {
            try {
                if (field == null) {
                    field = arrayListOf();
                }
                if (field!!.isNotEmpty()) {
                    for (mdbRejectAmount in field!!) {
                        mdbRejectAmount.enable = 1//默认启用
                    }
                    val mdbExcludeFromNextAmountBill = MdbParamsHelper.mdb_exclude_from_next_amount_bill
                    if (!mdbExcludeFromNextAmountBill.isNullOrEmpty()) {
                        for (value in mdbExcludeFromNextAmountBill) {
                            for (mdbRejectAmount in field!!) {
                                val credit = mdbRejectAmount.credit?.toDouble() ?: 0.0
                                if (credit == value) {
                                    //在配置文件中获取禁用值
                                    mdbRejectAmount.enable = 0
                                }
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return field
        }
    var z11Escrow = 255
    var low = 0//0：管道不用预警  非0：需要预警

    fun getTopOrderBalanceInt(): Double {
        return topOrderBalance
    }

}

object MdbHelper {

    val instanceMdbBean = MdbBean()

    ///mdb当前版本
    fun setMdbVersion(json: String) {
        val version = MdbUtil.jsonToAny<MdbVersion>(json, MdbVersion::class.java)?.compile_time
        if (!TextUtils.isEmpty(version)) {
            instanceMdbBean.version = version!!
        }
    }

    ///设置硬币器/纸币器状态
    /*
    {"cmd":"mdb_state_all","stat_coin":"mdb_offline_coin","stat_bill":"mdb_offline_bill",
    "stat_cashless":"mdb_offline_cashless","stat_changer":"cashless"}
     */
    fun setMdbStatus(json: String) {
        val stateAll = MdbUtil.jsonToAny<StateAll>(json, StateAll::class.java)
        instanceMdbBean.coinConnectionStatus = TextUtils.equals("mdb_online_coin", stateAll?.stat_coin)
        instanceMdbBean.billConnectionStatus = TextUtils.equals("mdb_online_bill", stateAll?.stat_bill)
        instanceMdbBean.cashlessConnectionStatus = TextUtils.equals("mdb_online_cashless", stateAll?.stat_cashless)
    }

    /*
    {"type":"coin","cmd":"setup","z1FeatureLevel":3,"z2z3CountryCodeType":1,"z2z3CountryCode10Val":643,"countryCodeAlphabetic":"RUB",
    "countryEntity":"Russian","countryCurrency":"Russian Ruble","currencySymbol":"₽","z4CoinScalingFactor":50,"z5DecimalPlaces":2,
    "z6z7CoinTypeRoutingAndz8z23Credit":[{"idx":0,"enable":0,"credit_val":1,"credit":"0.50","flag_coin":2},{"idx":1,"enable":0,"credit_val":1,
    "credit":"0.50","flag_coin":2},{"idx":2,"enable":1,"credit_val":2,"credit":"1.00","flag_coin":1},{"idx":3,"enable":0,"credit_val":4,"credit":"2.00",
    "flag_coin":2},{"idx":4,"enable":1,"credit_val":10,"credit":"5.00","flag_coin":1},{"idx":5,"enable":0,"credit_val":20,"credit":"10.00","flag_coin":2},
    {"idx":6,"enable":1,"credit_val":20,"credit":"10.00","flag_coin":1}]}
     */
    ///获取硬币器中的信息
    fun setCoinInfo(json: String) {
        //{"idx":3,"enable":0,"credit":"20.00"}
        val coinInfo = MdbUtil.jsonToAny<CoinInfo>(json, CoinInfo::class.java)
        val map = LinkedHashMap<Double, MDBRejectAmount>()

        coinInfo?.z6z7CoinTypeRoutingAndz8z23Credit?.forEach { //将重复币种排除
            val credit = it.credit.toDoubleOrNull() ?: 0.0
            map.put(credit, it)
        }

        val coinTubeInfo = arrayListOf<MDBRejectAmount>()
        coinTubeInfo.addAll(map.values)
        instanceMdbBean.coinTubeEnableList = coinTubeInfo
    }

    ///设置硬币器版本
    fun setCoinVersion(json: String) {
        val version = MdbUtil.jsonToAny<CoinExpan>(json, CoinExpan::class.java)?.z28z29SoftwareVersion
        if (!TextUtils.isEmpty(version)) {
            instanceMdbBean.coinVersion = version!!
        }
    }

    /*
    {"type":"coin","cmd":"tubeStatus","amount":"80.00","low":1,"z3z18TubeStatus":[{"idx":2,"credit":"1.00",
    "num":20,"full":0,"low_count":0,"low":0},{"idx":4,"credit":"5.00","num":12,"full":0,"low_count":0,"low":0},
    {"idx":6,"credit":"10.00","num":0,"full":0,"low_count":0,"low":1}]}
     */
    ///设置硬币器中余额
    fun setCoinBalance(json: String) {
        val coinBalance = MdbUtil.jsonToAny<CoinBalance>(json, CoinBalance::class.java)
        instanceMdbBean.coinTubeLowList = coinBalance?.z3z18TubeStatus
        instanceMdbBean.low = coinBalance?.low ?: 0
    }

    ///设置纸币器版本
    fun setBillVersion(json: String) {
        val version = MdbUtil.jsonToAny<BillExpan>(json, BillExpan::class.java)?.z28z29SoftwareVersion
        if (!TextUtils.isEmpty(version)) {
            instanceMdbBean.billVersion = version!!
        }
    }

    /*
    {"type":"bill","cmd":"setup","z1FeatureLevel":2,"z2z3CountryCodeType":0,"z2z3CountryCode10Val":643,"countryCodeAlphabetic":"RUB",
    "countryEntity":"Russian","countryCurrency":"Russian Ruble","currencySymbol":"₽","z4z5BillScalingFactor":1000,"z6DecimalPlaces":2,
    "z7z8StackerCapacity":300,"z9BillSecurityLevel":255,"z10BillSecurityLevel":255,"z11Escrow":255,"z12z27BillTypeCredit":[{"idx":0,"credit":"10.00"}
    ,{"idx":1,"credit":"50.00"},{"idx":2,"credit":"100.00"},{"idx":3,"credit":"200.00"},{"idx":4,"credit":"500.00"}]}
     */
    ///获取纸币器中的信息
    fun setBillInfo(json: String) {
        //{"idx":2,"credit":"500.00"}
        val billInfo = MdbUtil.jsonToAny<BillInfo>(json, BillInfo::class.java)

        val map = LinkedHashMap<Double, MDBRejectAmount>()

        billInfo?.z12z27BillTypeCredit?.forEach {//将重复币种排除
            val credit = it.credit.toDoubleOrNull() ?: 0.0
            map.put(credit, it)
        }

        val billEnableList = arrayListOf<MDBRejectAmount>()
        billEnableList.addAll(map.values)

        instanceMdbBean.billEnableList = billEnableList
        instanceMdbBean.z11Escrow = billInfo?.z11Escrow ?: 255
    }

    ///设置上次订单封单后余额
    fun setTopOrderBalance(json: String) {
        val mdbResult = MdbUtil.jsonToAny<MdbResult>(json, MdbResult::class.java)
        instanceMdbBean.topOrderBalance = mdbResult?.detail?.toDoubleOrNull() ?: 0.0
    }

    ///设置硬币器是否有空管道 mdbCbJsonS cmd = mdb_status_coin_enough , jsonStr = {"cmd":"mdb_status_coin_enough","result":"ok","detail":""}
    fun setHasEmptyCoinChannel(json: String) {
        val mdbResult = MdbUtil.jsonToAny<MdbResult>(json, MdbResult::class.java)
        instanceMdbBean.hasEmptyCoinChannel = !(mdbResult?.isOk() ?: true)
    }
}

///{"cmd":"mdb_sdk_version","compile_time":"2021-05-25 15:42"}
private class MdbVersion : Serializable {
    var compile_time: String? = null//版本时间
}

/*
{"cmd":"mdb_state_all","stat_coin":"mdb_online_coin","stat_bill":"mdb_offline_bill","stat_cashless":
"mdb_offline_cashless","stat_changer":"coin"}
 */
private class StateAll : Serializable {
    var stat_coin: String? = null//在线/离线 mdb_online_coin/mdb_offline_coin
    var stat_bill: String? = null//在线/离线 mdb_online_bill/mdb_offline_bill
    var stat_cashless: String? = null//在线/离线 mdb_online_cashless/mdb_offline_cashless
}

/*
{"type":"coin","cmd":"setup","z1FeatureLevel":3,"z2z3CountryCodeType":1,"z2z3CountryCode10Val":901,
"countryCodeAlphabetic":"TWD","countryEntity":"TAIWAN, PROVINCE","countryCurrency":"New Taiwan Dollar",
"currencySymbol":"NT＄","z4CoinScalingFactor":1,"z5DecimalPlaces":0,"z6z7CoinTypeRoutingAndz8z23Credit":
[{"idx":0,"enable":0,"credit":"1.00"},{"idx":1,"enable":1,"credit":"5.00"},{"idx":2,"enable":1,"credit":"10.00"}
,{"idx":3,"enable":0,"credit":"20.00"},{"idx":4,"enable":1,"credit":"50.00"}]}
 */
private class CoinInfo : Serializable {
    val z6z7CoinTypeRoutingAndz8z23Credit: List<MDBRejectAmount>? = null
}

/*
{"type":"coin","cmd":"expansion00","z1z3ManufacturerCode":"ICT","z4z15SerialNumber":"200500002938",
"z16z27ModelOrTuningRevision":"CCM6-TWD MDB","z28z29SoftwareVersion":"0.7.0.3","z33b0AlternativePayoutmethod":1,
"z330b1ExtDiagCmdSupported":1,"z33b2CtrlManualFillAndPayoutCmdSupported":1,"z33b3FileTransLayerSupported":1}
 */
private class CoinExpan : Serializable {
    val z28z29SoftwareVersion: String? = null
}

/*
{"type":"coin","cmd":"tubeStatus","amount":"160.00","z3z18TubeStatus":[{"idx":1,"credit":"5.00",
"num":0,"full":0},{"idx":2,"credit":"10.00","num":11,"full":0},{"idx":4,"credit":"50.00","num":1,"full":0}]}
 */
private class CoinBalance : Serializable {
    val z3z18TubeStatus: List<MDBRejectAmount>? = null
    val low = 0
}

/*
{"type":"bill","cmd":"setup","z1FeatureLevel":1,"z2z3CountryCodeType":0,"z2z3CountryCode10Val":901,
"countryCodeAlphabetic":"TWD","countryEntity":"TAIWAN, PROVINCE","countryCurrency":"New Taiwan Dollar",
"currencySymbol":"NT＄","z4z5BillScalingFactor":1000,"z6DecimalPlaces":2,"z7z8StackerCapacity":200,
"z9BillSecurityLevel":0,"z10BillSecurityLevel":15,"z11Escrow":255,"z12z27BillTypeCredit":[{"idx":0,"credit":"100.00"},
{"idx":1,"credit":"200.00"},{"idx":2,"credit":"500.00"},{"idx":3,"credit":"1000.00"}]}
 */
private class BillInfo : Serializable {
    val z12z27BillTypeCredit: List<MDBRejectAmount>? = null
    val countryCodeAlphabetic: String? = null
    val z11Escrow = 0//是否具有 escrow 能力[0 表示没有，255 表示有]
}

/*
{"type":"bill","cmd":"expansion02","z1z3ManufacturerCode":"ICT","z4z15SerialNumber":"////////////",
"z16z27ModelOrTuningRevision":"V7E+TWD40000","z28z29SoftwareVersion":"0.1.0.1"}
 */
private class BillExpan : Serializable {
    val z28z29SoftwareVersion: String? = null
}

///{"cmd":"mdb_status_coin_enough","result":"err","detail":""}
///{"cmd":"mdb_get_balance","result":"ok","detail":"0.0"}
open class MdbResult : Serializable {
    val result: String? = null//ok/err
    val detail: String? = null

    fun isOk(): Boolean {
        return TextUtils.equals("ok", result)
    }
}

///订单支付过程中回调
//开始 {"cmd":"mdb_order","result":"ok","detail":"start","amount_info":"20.00"}
//结束 {"cmd":"mdb_order","result":"ok","detail":"end","amount_want":"20.00","amount_deposited":"20.00"}
//错误 {"cmd":"mdb_order","result":"err","detail":"calc_credit_diff"}
class MdbPayOrderBean : MdbResult() {
    //当 result 值为：err 时,detail内容如屑
    fun getErrDesc(): String {
        return when (detail) {
            "param_type_not_cashes_or_cashless" -> "表示 type 类型参数错误，\n" +
                    "值不是 cashes 或 cashless 其中之一"
            "param_amount_incorrect" -> "表示 amount 金额参数小于等于 0，不正确"
            "param_timeout_incorrect" -> "表示 timeout 超时参数的输入值不正确"
            "in_progress" -> "表示上次已下订单未结束，此次请求忽略"
            "un_finished" -> "表示上笔订单未结束"
            "over_max_order_price" -> "表示请求金额超过初始化时指定的最大订单金额"
            "set_timeout_failed" -> "表示设置超时时间失败"
            "preset_no_coin_or_bill" -> "表示既没启用硬币器也没启用纸币器"
            "credit_error_or_offline" -> "计算订单金额错误或设备掉线"
            "calc_credit_diff" -> "计算金额有误差"
            "timeout" -> "表示此次订单超时未完成，订单结束，即将进入超时处理流程\n" +
                    "（mdb_timeout_cancel）"
            "end_chk_dispense_not_enough" -> "表示订单金额已收足，但预校验找零判断为不足"
            "pause" -> "纸币订单当中，如设备掉线，则订单暂停收钞"
            "continue" -> "纸币订单当中，如设备重新上线，则订单可以继续收钞"
            else -> ""
        }
    }

    //当 result 值为：ok 时,detail内容如屑
    fun getOkDesc(): String {
        return when (detail) {
            "start" -> "表示此次请求订单已启动，可以开始投纸币了"
            "end" -> "表示此次订单金额已收，结束纸币器结束收钞，订单收款结束，如果入币金\n" +
                    "额大于订单金额，SDK 会自动进入超额退款处理流程（mdb_over_cancel）"
            else -> ""
        }
    }
}

/*
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Just Reset"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Vend Denied"}
{"cmd":"mdb_order","result":"ok","detail":"vend_denied","amount_order":"5.00","amount_deposited":"0.00"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"End Session"}
{"cmd":"mdb_order_finish","result":"ok","detail":"end_sess"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Begin Session"}
{"cmd":"mdb_order_none","result":"ok","detail":"sess_complete","amount_order":"0.00","amount_deposited":"0.00"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"End Session"}
{"cmd":"mdb_order_finish","result":"ok","detail":"end_sess"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Begin Session"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"End Session"}
{"cmd":"mdb_order_finish","result":"ok","detail":"end_sess"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Begin Session"}
{"cmd":"mdb_order_none","result":"ok","detail":"sess_complete","amount_order":"0.00","amount_deposited":"0.00"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"End Session"}
{"cmd":"mdb_order_finish","result":"ok","detail":"end_sess"}
{"cmd":"mdb_poll_cashless","state":"ok","detail":"Begin Session"}
{"cmd":"mdb_order_none","result":"ok","detail":"sess_complete","amount_order":"0.00","amount_deposited":"0.00"}
 */
class CashlessPayOrderBean : MdbResult() {
    val cmd: String? = null
    val state: String? = null

    fun isStateOk(): Boolean {
        return TextUtils.equals(state, "ok")
    }

    fun isResultOk(): Boolean {
        return isOk()
    }
}

///收到硬币: {"cmd":"mdb_deposited_coin","result":"ok","amount_deposited":"10.00","amount_total":"10.00","amount_recycler":""}
/*
///收到纸币:
mdbCbJsonS cmd = mdb_deposited_bill , jsonStr = {"cmd":"mdb_deposited_bill","result":"ok","flag_coin":-1,
"vend_deposited":0,"vend_token":0,"amount_deposited":"100.00","amount_total":"100.00","amount_escrow":"no","amount_recycler":"0.0"}
 */
class MdbReceiveAmountBean {
    private val cmd: String? = null
    private val result: String? = null//ok/err

    //    private val flag_coin = 0//(备注：3-vend token; 2-value token; 1-coin; -1 忽略)
//    private val vend_deposited=0//(备注：本次投入 vend token 的个数 0 或 1)
//    private val vend_token=0//(备注：当前投入 vend token 的总个数)
    private val amount_deposited: String? = null//已收到金额 (备注：当本次投入 vend token 时为 0.0)
    val amount_total: String? = null//累计投入金额

    //    private  val amount_escrow="yes"//(备注：是否为暂存纸币)
//    private val amount_recycler: String? = null//对于纸币器回收箱而言，剩余可退款总金额
    fun isOk(): Boolean {
        return TextUtils.equals("ok", result)
    }

    ///是否是硬币
    fun isCoin(): Boolean {
        return TextUtils.equals(cmd, "mdb_deposited_coin")
    }

    fun amountTypeText(): String {
        return if (isCoin()) {
            return "硬币"
        } else {
            return "纸币"
        }
    }

    ///当前收到金额
    fun depositedAmount(): Double {
        return amount_deposited?.toDoubleOrNull() ?: 0.0
    }

    ///共收到金额
    fun totaldAmount(): Double {
        return amount_total?.toDoubleOrNull() ?: 0.0
    }
}

//开始找零 {"cmd":"mdb_over_cancel","result":"ok","detail":"start","amount_want":"20.00","amount_deposited":"50.00"}
//结束找零 {"cmd":"mdb_over_cancel","result":"ok","detail":"end_ok","amount_want":"30.00","amount_dispense":"30.00"}
class MdbOverCancelBean : MdbResult() {
    private val amount_want: String? = null//
    private val amount_deposited: String? = null//
    fun print(): String {
        if (TextUtils.equals("start", detail)) {
            val diffPrice = (amount_deposited?.toDoubleOrNull()
                    ?: 0.0) - (amount_want?.toDoubleOrNull()
                    ?: 0.0)
            return "支付金额超过订单金额,自动找零开始,找零金额:${diffPrice}"
        } else if (TextUtils.equals("end_ok", detail)) {
            return "支付金额超过订单金额,自动找零结束"
        }
        return ""
    }
}

class MdbStateBean {
    private val state: String? = null
    val detail: String? = null
    fun stateError(): Boolean {
        return TextUtils.equals("err", state)
    }
}

object MdbCashlessConstans {
    val PaySucessText = "{\"cmd\":\"mdb_order_finish\",\"result\":\"ok\",\"detail\":\"end_sess\"}"
}

///所有动作指令
enum class MdbCmdType(val cmd: String, val desc: String) {
    //以下都是被动下发指令
    mdb_poll_cashless("mdb_poll_cashless", "mdb刷卡"),
    mdb_sdk_version("mdb_sdk_version", "mdb当前版本"),
    mdb_state_all("mdb_state_all", "设置硬币器/纸币器联机状态"),
    mdb_coin_setup("mdb_coin_setup", "获取硬币器中的信息"),
    mdb_coin_expan("mdb_coin_expan", "设置硬币器版本"),
    mdb_status_coin("mdb_status_coin", "设置硬币器中各币种详情"),
    mdb_bill_setup("mdb_bill_setup", "获取纸币器中的信息"),
    mdb_bill_expan("mdb_bill_expan", "设置纸币器版本"),
    mdb_action("mdb_action", "mdb指令"),
    mdb_poll_coin("mdb_poll_coin", "硬币器状态"),
    mdb_poll_bill("mdb_poll_bill", "纸币器状态"),
    mdb_dispensed_coin("mdb_dispensed_coin", "已退硬币"),
    mdb_order_last("mdb_order_last", "塞入纸币未完成，遇系统断电"),
    mdb_dev_info("mdb_dev_info", "mdb初始化完成"),
    mdb_deposited_coin("mdb_deposited_coin", "付款过程中： 收到了硬币的回调"),
    mdb_deposited_bill("mdb_deposited_bill", "付款过程中： 收到了纸币的回调"),

    mdb_timeout_cancel("mdb_timeout_cancel", "支付超时"),
    mdb_over_cancel("mdb_over_cancel", "支付金额大于订单金额,自动找零"),

    //以下都是主动下发指令
    GetBillDetail("mdb_dispense_status_bill", "查询零钱"),
    PayOrder("mdb_order", "下单支付"),
    CancelOrder("mdb_order_cancel", "取消订单"),
    FinishOrder("mdb_order_finish", "订单结束"),
    RefundAmountBill("mdb_dispense_bill", "纸币退钞"),
    RefundAmountCoin("mdb_dispense_coin", "硬币退钞"),
    StuckAmount("escrow_coins", "卡币退款"),
    GetTopOrderBalance("mdb_get_balance", "上一笔订单结束后余额"),
    GetHasEmptyCoinChannel("mdb_status_coin_enough", "查询硬币器管道是否有空管道"),

    mdbAction("mdbAction", "下发指令握手确认"),
    mdbPreInit("mdbPreInit", "预初始动作"),
    mdb_get_all_type_bill("mdb_get_all_type_bill", "查询所有纸币面额"),
    mdb_order_prechk_continue("mdb_order_prechk_continue", "找零不足时订单继续")
}